<template>
  <dogeo-map @mounted="handleMountMap" :options="options" ref="dogeoMap" class="view-download">
    <template v-slot:menu-start>
      <el-popover
        placement="right-end"
        title=""
        width="260"
        trigger="hover"
        popper-class="popover-plain">
        <span @click="handleStartDraw" slot="reference" class="menu-icon"><i class="el-icon-crop"></i></span>
        <div><b>绘制矩形：</b></div>
        <div>1、左键单击此图标开启绘制；</div>
        <div>2、左键单击地图建立起始点；</div>
        <div>3、左键单击地图建立结束点；</div>
        <div>4、右键单击确认矩形区域结束绘制</div>
      </el-popover>
      <el-popover
        placement="right-end"
        title=""
        width="200"
        trigger="hover"
        content="下载瓦片"
        popper-class="popover-plain">
        <span @click="drawer = true" slot="reference" class="menu-icon"><i class="el-icon-download"></i></span>
      </el-popover>
      <el-popover
        placement="right-end"
        title=""
        width="200"
        trigger="hover"
        content="任务管理"
        popper-class="popover-plain">
        <span @click="handleShowTask" slot="reference" class="menu-icon"><i class="el-icon-s-order"></i></span>
      </el-popover>
      <el-popover
        placement="right-end"
        title=""
        width="200"
        trigger="hover"
        content="清除绘制的矩形"
        popper-class="popover-plain">
        <span @click="handleClearDraw" slot="reference" class="menu-icon"><i class="el-icon-delete"></i></span>
      </el-popover>
      <el-popover
        placement="right-end"
        title=""
        width="320"
        trigger="hover"
        content="帮助"
        popper-class="popover-plain">
        <span slot="reference" class="menu-icon"><i class="el-icon-question"></i></span>
        <div><b>瓦片地址方式一：按路径访问</b></div>
        <div>天地图瓦片地址(示例)：</div>
        <div>http://127.0.0.1:8100/map/tile/tianditu/cva_w/wmts/{z}/{x}/{y}.png</div>
        <div>http://127.0.0.1:8100/map/tile/tianditu/cva_w/wmts/1/1/0.png</div>
        <div>高德地图访问地址(示例)：</div>
        <div>http://127.0.0.1:8100/map/tile/autonavi/vec/wmts/{z}/{x}/{y}.png</div>
        <div>http://127.0.0.1:8100/map/tile/autonavi/vec/wmts/1/1/0.png</div>
        <div><b>瓦片地址方式二：按参数访问</b></div>
        <div>天地图瓦片地址(示例)：</div>
        <div>http://127.0.0.1:8100/tianditu/vec_w/wmts?service=WMTS&request=GetTile&version=1.0.0&layer={layer}&tileMatrixSet={tileMatrixSet}&tilematrix={tilematrix}&tilerow={tilerow}&tilecol={tilecol}</div>
        <div>http://127.0.0.1:8100/tianditu/vec_w/wmts?service=WMTS&request=GetTile&version=1.0.0&layer=vec&tileMatrixSet=w&tilematrix=1&tilerow=1&tilecol=0</div>
        <div>高德地图访问地址(示例)：</div>
        <div>http://127.0.0.1:8100/autonavi/appmaptile?vec=1&z={z}&x={x}&y={y}.png</div>
        <div>http://127.0.0.1:8100/autonavi/appmaptile?vec=1&z=1&x=1&y=0.png</div>
      </el-popover>
    </template>
    <el-drawer
      title="下载瓦片"
      :visible.sync="drawer"
      :direction="direction"
      :append-to-body="true"
      :before-close="handleCloseDrawer"
      size="320px"
      custom-class="drawer-active">
      <div class="box-info">
        <el-form ref="form" :model="form" label-width="80px" size="small">
          <el-form-item label="坐标范围">
            <el-input v-model="form.range" type="textarea" rows="4"></el-input>
          </el-form-item>
          <el-form-item label="地图级别" class="checkbox-min">
            <div style="padding: 2px 8px;border: 1px solid #DCDFE6;border-radius: 4px;text-align: left">
              <el-checkbox-group v-model="form.levels">
                <el-checkbox
                  v-for="item in mapLevels" :key="item"
                  :label="item"
                  :name="'' + item"></el-checkbox>
              </el-checkbox-group>
            </div>
          </el-form-item>
          <el-form-item label="地图图层">
            <div style="color:#666">
              <div v-for="(item, i) in getLayers()" :key="i">
                <span>{{ item.map.name }}</span>
                <span>-</span>
                <span>{{ item.layer.name }}</span>
                <span></span>
              </div>
            </div>
          </el-form-item>
          <el-form-item label="瓦片信息" label-position="top">
            <el-table
              :data="tileData"
              :border="true"
              :stripe="true"
              size="mini"
              height="200px"
              style="width: 100%">
              <el-table-column
                prop="level"
                label="级别"
                width="60">
              </el-table-column>
              <el-table-column
                prop="count"
                label="数量">
              </el-table-column>
            </el-table>
          </el-form-item>
        </el-form>
        <div class="btns-footer">
          <el-button @click="handleBuild" type="primary" size="mini">创建任务</el-button>
          <el-button v-if="isBuilt && !isStarted" @click="handleStart" type="success" size="mini">开始下载</el-button>
          <el-button v-if="isStarted" @click="handleGoTask" type="danger" size="mini">查看任务</el-button>
        </div>
      </div>
    </el-drawer>
    <el-drawer
      title="任务管理"
      :visible.sync="isShowTask"
      :direction="direction"
      :append-to-body="true"
      size="100vw"
      custom-class="drawer-active">
      <div class="box-info">
        <div class="grid-tools">
          <div>
            <el-button @click="handleStop" type="danger" size="mini">停止所有任务</el-button>
          </div>
          <div>
            <el-button @click="handleSearch" icon="el-icon-refresh-right" circle size="mini"></el-button>
          </div>
        </div>
        <el-table
          :data="taskData"
          :border="true"
          :stripe="true"
          size="mini"
          style="width: 100%">
          <el-table-column
            prop="map"
            label="地图"
            width="100">
          </el-table-column>
          <el-table-column
            prop="layer"
            label="图层"
            width="140">
          </el-table-column>
          <el-table-column
            prop="key"
            label="标识"
            width="100">
          </el-table-column>
          <el-table-column
            prop="range"
            label="坐标范围">
          </el-table-column>
          <el-table-column
            prop="levels"
            label="级别"
            width="80">
          </el-table-column>
          <el-table-column
            prop="successCount"
            label="已下载"
            width="70">
          </el-table-column>
          <el-table-column
            prop="waitCount"
            label="待下载"
            width="70">
          </el-table-column>
          <el-table-column
            prop="failCount"
            label="失败"
            width="70">
          </el-table-column>
          <el-table-column
            prop="sum"
            label="总数"
            width="70">
          </el-table-column>
          <el-table-column
            prop="time"
            label="创建时间"
            width="140">
          </el-table-column>
          <el-table-column
            prop="status"
            label="状态"
            width="80">
            <template slot-scope="scope">
              <el-tag 
                :type="getStatusType(scope.row.status)" 
                size="mini">
                {{ getStatusText(scope.row.status) }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column
            prop="progress"
            label="进度"
            width="100">
            <template slot-scope="scope">
              <el-progress 
                :percentage="getProgress(scope.row)" 
                :stroke-width="6"
                :show-text="false"
                size="mini">
              </el-progress>
              <span style="font-size: 12px; color: #666;">
                {{ getProgressText(scope.row) }}
              </span>
            </template>
          </el-table-column>
          <el-table-column
            prop="action"
            label="操作"
            width="160">
            <template slot-scope="scope">
              <el-button 
                v-if="scope.row.status === 0" 
                @click="handleTurnOnTask(scope.row)" 
                type="text" 
                size="small">继续</el-button>
              <el-button 
                v-if="scope.row.status === 1" 
                @click="handleStopTask(scope.row)" 
                type="text" 
                size="small">停止</el-button>
              <el-button 
                @click="handleDeleteTask(scope.row)" 
                type="text" 
                size="small">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </el-drawer>
  </dogeo-map>
</template>

<script>
import * as Cesium from 'cesium'
import DogeoMap from '@/components/dogeo/map.vue'
import { DrawRectangle } from '@/components/dogeo/cesium/draw/draw-rect.js'
import { Cartesian3_to_WGS84, lon2tilex, lat2tiley } from '@/components/dogeo/cesium/transform.js'
import providers from '@/components/dogeo/providers/providers.js'
const config = (window.application || {}).dmapt || {}

export default {
  name: 'dmapt-download',

  components: {
    DogeoMap
  },

  data() {
    let mode = ((window.application || {}).dmapt || {}).mode || {}
    const cesiumSetting = (mode || {}).cesium || {}
    return {
      viewer: null,
      options: Object.assign(cesiumSetting, {
        isStoreLayers: true
      }),
      form: {
        mode: 'web_mercator',
        layers: [1002, 1004],
        levels: [1, 2, 3, 4, 5, 6],
        range: ''
      },
      // 地图层级
      mapLevels: [
        1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
        11, 12, 13, 14, 15, 16, 17, 18, 19, 20
      ],
      // 瓦片信息
      tileData: [],
      // 表单数据
      formData: {},
      // 是否创建好
      isBuilt: false,
      drawer: false,
      direction: 'ltr',
      // 任务管理
      isShowTask: false,
      isStarted: false,
      taskData: [],
      refreshTimer: null
    }
  },

  mounted() {
    // 启动自动刷新
    this.startAutoRefresh()
  },

  beforeDestroy() {
    // 清理定时器
    this.stopAutoRefresh()
  },

	methods: {
    // 地图加载完成
    handleMountMap ({ viewer } = {}) {
      this.viewer = viewer
    },
    // 获取选择的图层
    getLayers () {
      let nodes = []
      if (this.$refs.dogeoMap) {
        nodes = this.$refs.dogeoMap.getBaseLayers()
      }
      // 过滤基础底图
      nodes = nodes.filter(item => {
        return item.map.map !== 'basic'
      })
      return nodes
    },
    // 开始绘制
    handleStartDraw () {
      if (!this.recter) {
        this.recter = new DrawRectangle({
          viewer: this.viewer,
          Cesium,
          callback: () => {
            let cords = this.getRects()
            cords = cords.map(item => {
              return item.lon + ',' + item.lat
            }).join('-')
            this.form.range = cords
          }
        })
      }
      this.recter.startCreate()
    },
    // 清除绘制
    handleClearDraw () {
      if (this.recter) {
        this.recter.clear()
      }
      this.form.range = ''
    },
    getRects () {
      // 范围
      let rects = []
      if (this.recter) {
        rects = this.recter.getData() || []
      }
      rects = rects.map(cartesian3 => {
        let wgs84 = Cartesian3_to_WGS84(cartesian3)
        return wgs84
      })
      // 瓦片坐标
      let cords = []
      if (rects.length) {
        cords = [
          { lon: rects[0].lng, lat: rects[0].lat },
          { lon: rects[rects.length - 1].lng, lat: rects[rects.length - 1].lat }
        ]
      }

      return cords
    },
    // 创建任务
    handleBuild () {
      // 图层
      let layers = this.getLayers()
      if (!layers.length) {
        this.$message({
          message: '未选择地图图层',
          type: 'error'
        })
        return false
      }
      // 层级
      if (!this.form.levels.length) {
        this.$message({
          message: '未选择地图层级',
          type: 'error'
        })
        return false
      }
      // 瓦片范围
      let cords = this.getRects()
      if (!cords.length) {
        this.$message({
          message: '未绘制区域，点击左上角图标开始绘制',
          type: 'error'
        })
        return false
      }
      let levels = this.form.levels.sort(function(a, b){
        return a > b ? 1 : a < b ? -1 : 0
      })
      this.tileData = levels.map(zoom => {
        return {
          level: zoom,
          count: this.getTileCount(zoom, cords)
        }
      })
      // 保留表单数据
      this.formData = {
        layers: layers.map(item => {
          return {
            map: item.map.map,
            layer: item.layer.layer,
            path: item.layer.path
          }
        }),
        levels: this.form.levels.map(item => item),
        range: [cords[0].lon, cords[0].lat, cords[1].lon, cords[1].lat]
      }
      this.isBuilt = true
      this.isStarted = false
    },
    // 开始下载
    handleStart () {
      fetch(this.getServer() + '/tile/task/download', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        mode: 'cors',
        body: JSON.stringify(this.formData)
      }).then(res => {
        if (res.status === 200) {
          return res.json()
        } else {
          return Promise.reject(res.json())
        }
      }).then((data) => {
        if (data.success) {
          this.$message({
            message: '任务执行成功，点击任务查看下载详细',
            type: 'success'
          })
          this.isStarted = true
        } else {
          this.$message({
            message: data.msg || '任务执行失败',
            type: 'error'
          })
        }
      }).catch((err) => {
        this.$message({
          message: '任务执行失败',
          type: 'error'
        })
        console.log(err)
      })
    },
    // 结束下载
    handleStop () {
      this.$confirm('确认操作吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.fetchStop()
      }).catch(() => {})
    },
    fetchStop () {
      fetch(this.getServer() + '/tile/task/stop', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        mode: 'cors'
      }).then(res => {
        if (res.status === 200) {
          return res.json()
        } else {
          return Promise.reject(res.json())
        }
      }).then((data) => {
        if (data.success) {
          this.$message({
            message: '操作成功',
            type: 'success'
          })
        } else {
          this.$message({
            message: data.msg || '操作失败',
            type: 'error'
          })
        }
      }).catch((err) => {
        this.$message({
          message: '操作成功',
          type: 'error'
        })
        console.log(err)
      })
    },
    // 显示任务
    handleGoTask () {
      this.drawer = false
      this.handleShowTask()
    },
    // 获取某个等级的瓦片数量
    getTileCount(level, cords) {
      let x = lon2tilex(cords[0].lon, level)
      let y = lat2tiley(cords[0].lat, level)
      let x1 = lon2tilex(cords[1].lon, level)
      let y1 = lat2tiley(cords[1].lat, level)
      let startx = Math.min(x, x1), endx = Math.max(x, x1)
      let starty = Math.min(y, y1), endy = Math.max(y, y1)
      return (endx - startx + 1) * (endy - starty + 1)
    },
    // 获取不同缩放等级的数量
    getTileLayers(levels, cords) {
      let list = []
      levels.forEach(level => {
        level = parseInt(level)
        let x = lon2tilex(cords[0].lon, level)
        let y = lat2tiley(cords[0].lat, level)
        let x1 = lon2tilex(cords[1].lon, level)
        let y1 = lat2tiley(cords[1].lat, level)
        let startx = Math.min(x, x1), endx = Math.max(x, x1)
        let starty = Math.min(y, y1), endy = Math.max(y, y1)
        for (let i = startx; i <= endx; i++) {
          for (let j = starty; j <= endy; j++) {
            list.push({ x: i, y: j, level })
          }
        }
      })
      return list
    },
    // 关闭窗口
    handleCloseDrawer(done) {
      done()
    },
    // 获取服务主机
    getServer () {
      let rules = (config.mode || {}).rules || []
      let server = (rules.find(item => item.rule === 'host') || {}).url
      return server
    },
    // 显示任务
    handleShowTask () {
      this.isShowTask= true
      this.handleSearch()
    },
    // 查询数据
    handleSearch () {
      fetch(this.getServer() + '/tile/task/query', {
        method: 'get',
        headers: {
          'Content-Type': 'application/json'
        },
        mode: 'cors'
      }).then(res => {
        if (res.status === 200) {
          return res.json()
        } else {
          return Promise.reject(res.json())
        }
      }).then((res) => {
        let list = ((res || {}).data || {}).list
        list = Array.isArray(list) ? list : []
        list = list.map(item => {
          let value = item.value
          let provider = providers.find(node => node.map === value.map) || {}
          item.map = provider.name || ''
          let layers = Array.isArray(provider.layers) ? provider.layers : []
          item.layer = (layers.find(node => node.path === value.path) || {}).name || ''
          item.levels = value.levels.join(',')
          item.range = value.range.join(',')
          item.sum = value.sum
          item.time = value.time
          item.status = value.status || 0 // 添加状态字段
          item.successCount = value.tiles.filter(item => item.success === 1).length
          item.failCount = value.tiles.filter(item => item.fail === 1).length
          item.waitCount = value.tiles.length - item.successCount - item.failCount
          item.waitCount = item.waitCount < 0 ? 0 : item.waitCount
          return item
        })
        list = list.sort((a, b) => {
          let ta = new Date(a.time).getTime(), tb = new Date(b.time).getTime()
          return ta > tb ? -1 : ta < tb ? 1 : 0
        })
        this.taskData = list
      })
    },
    // 继续任务
    handleTurnOnTask(row) {
      this.$confirm('确认继续此任务吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.fetchResumeTask(row.key)
      }).catch(() => {})
    },
    // 停止任务
    handleStopTask(row) {
      this.$confirm('确认停止此任务吗?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.fetchStopTask(row.key)
      }).catch(() => {})
    },
    // 删除任务
    handleDeleteTask (row) {
      this.$confirm('确认删除此任务吗? 删除后无法恢复', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.fetchDeleteTask(row.key)
      }).catch(() => {})
    },
    // 继续任务请求
    fetchResumeTask(key) {
      fetch(this.getServer() + '/tile/task/resume/' + key, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        mode: 'cors'
      }).then(res => {
        if (res.status === 200) {
          return res.json()
        } else {
          return Promise.reject(res.json())
        }
      }).then((data) => {
        if (data.success) {
          this.$message({
            message: data.msg || '任务已恢复',
            type: 'success'
          })
          this.handleSearch() // 刷新任务列表
        } else {
          this.$message({
            message: data.msg || '任务恢复失败',
            type: 'error'
          })
        }
      }).catch((err) => {
        this.$message({
          message: '任务恢复失败',
          type: 'error'
        })
        console.log(err)
      })
    },
    // 停止任务请求
    fetchStopTask(key) {
      fetch(this.getServer() + '/tile/task/stop/' + key, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        mode: 'cors'
      }).then(res => {
        if (res.status === 200) {
          return res.json()
        } else {
          return Promise.reject(res.json())
        }
      }).then((data) => {
        if (data.success) {
          this.$message({
            message: data.msg || '任务已停止',
            type: 'success'
          })
          this.handleSearch() // 刷新任务列表
        } else {
          this.$message({
            message: data.msg || '任务停止失败',
            type: 'error'
          })
        }
      }).catch((err) => {
        this.$message({
          message: '任务停止失败',
          type: 'error'
        })
        console.log(err)
      })
    },
    // 删除任务请求
    fetchDeleteTask(key) {
      fetch(this.getServer() + '/tile/task/delete/' + key, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        mode: 'cors'
      }).then(res => {
        if (res.status === 200) {
          return res.json()
        } else {
          return Promise.reject(res.json())
        }
      }).then((data) => {
        if (data.success) {
          this.$message({
            message: data.msg || '任务已删除',
            type: 'success'
          })
          this.handleSearch() // 刷新任务列表
        } else {
          this.$message({
            message: data.msg || '任务删除失败',
            type: 'error'
          })
        }
      }).catch((err) => {
        this.$message({
          message: '任务删除失败',
          type: 'error'
        })
        console.log(err)
      })
    },
    // 获取状态类型
    getStatusType(status) {
      switch (status) {
        case 0: return 'warning' // 已停止
        case 1: return 'success' // 运行中
        case 2: return 'info' // 已完成
        default: return 'info'
      }
    },
    // 获取状态文本
    getStatusText(status) {
      switch (status) {
        case 0: return '已停止'
        case 1: return '运行中'
        case 2: return '已完成'
        default: return '未知'
      }
    },
    // 获取进度百分比
    getProgress(row) {
      if (!row.sum || row.sum === 0) return 0
      let completed = row.successCount + row.failCount
      return Math.round((completed / row.sum) * 100)
    },
    // 获取进度文本
    getProgressText(row) {
      let completed = row.successCount + row.failCount
      return `${completed}/${row.sum}`
    },
    // 启动自动刷新
    startAutoRefresh() {
      this.refreshTimer = setInterval(() => {
        if (this.isShowTask) {
          this.handleSearch()
        }
      }, 3000) // 每3秒刷新一次
    },
    // 停止自动刷新
    stopAutoRefresh() {
      if (this.refreshTimer) {
        clearInterval(this.refreshTimer)
        this.refreshTimer = null
      }
    }
	}
}
</script>

<style lang="less">
@import '@/components/dogeo/cesium/widget/navigation/style/navigation.less';
.view-download {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
}
.box-info {
  padding: 4px 4px 56px;
  .el-form-item {
    margin-bottom: 8px;
  }
  .checkbox-min {
    .el-checkbox {
      margin-right: 8px;
      width: 42px;
      line-height: 18px;
    }
  }
  .el-checkbox__label {
    padding-left: 6px;
  }
  .el-select {
    display: block;
  }
  .btns-footer {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    padding: 8px;
    text-align: center;
    border-top: 1px solid #EBEEF5;
    z-index: 11;
    background: rgba(255, 255, 255, 0.8);
  }
}
.grid-tools {
  display: flex;
  padding: 4px 0;
  align-items: center;
  justify-content: space-between;
}
</style>